package com.lightboat.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.lightboat.common.annotation.DataScope;
import com.lightboat.common.api.BaiDuJianKangApi;
import com.lightboat.common.config.properties.OpenApiCredentialProperties;
import com.lightboat.common.constant.Constants;
import com.lightboat.common.constant.RedisConstants;
import com.lightboat.common.core.domain.bo.CommonCargoInfoBo;
import com.lightboat.common.core.domain.bo.LogisticsOrderBo;
import com.lightboat.common.core.domain.bo.OrderProductBo;
import com.lightboat.common.core.domain.entity.SysUser;
import com.lightboat.common.core.text.Convert;
import com.lightboat.common.enums.*;
import com.lightboat.common.exception.ServiceException;
import com.lightboat.common.manager.AsyncManager;
import com.lightboat.common.utils.*;
import com.lightboat.system.domain.*;
import com.lightboat.system.domain.request.*;
import com.lightboat.system.mapper.*;
import com.lightboat.system.service.ICrmOrderService;
import com.lightboat.system.service.ICrmProductService;
import com.lightboat.system.service.ICrmUserFollowRecordService;
import com.lightboat.system.service.IJdLogisticsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 *
 * @author lightboat
 * @date 2025-08-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CrmOrderServiceImpl extends ServiceImpl<CrmOrderMapper, CrmOrder> implements ICrmOrderService {

    private final CrmOrderMapper crmOrderMapper;
    private final OpenApiCredentialProperties apiCredentialProperties;
    private final CrmCustomerMapper crmCustomerMapper;
    private final CrmUserFollowRelationMapper crmUserFollowRelationMapper;
    private final IJdLogisticsService jdLogisticsService;
    private final ICrmUserFollowRecordService crmUserFollowRecordService;
    private final CrmProductStockRecordMapper crmProductStockRecordMapper;

    private final CrmProductMapper crmProductMapper;
    private final SysUserMapper sysUserMapper;
    private final CrmLogisticsRecordMapper crmLogisticsRecordMapper;
    private final TransactionTemplate transactionTemplate;
    private final ICrmProductService crmProductService;

    /**
     * 查询订单
     *
     * @param orderId 订单主键
     * @return 订单
     */
    @Override
    public CrmOrder selectCrmOrderByOrderId(Long orderId) {
        return crmOrderMapper.selectCrmOrderByOrderId(orderId);
    }

    /**
     * 查询订单列表
     *
     * @param crmOrder 订单
     * @return 订单
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<CrmOrder> selectCrmOrderList(CrmOrder crmOrder) {
        return crmOrderMapper.selectCrmOrderList(crmOrder,null);
    }

    /**
     * 查询订单列表
     * @param crmOrder
     * @param queryWrapper
     * @return
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<CrmOrder> selectCrmOrderList(CrmOrder crmOrder, Wrapper<?> queryWrapper) {
        return crmOrderMapper.selectCrmOrderList(crmOrder,queryWrapper);
    }

    /**
     * 新增订单
     *
     * @param crmOrder 订单
     * @return 结果
     */
    @Override
    public int insertCrmOrder(CrmOrder crmOrder) {
        crmOrder.setCreateTime(DateUtils.getNowDate());
        return crmOrderMapper.insert(crmOrder);
    }

    /**
     * 修改订单
     *
     * @param crmOrder 订单
     * @return 结果
     */
    @Override
    public int updateCrmOrder(CrmOrder crmOrder) {
        crmOrder.setUpdateTime(DateUtils.getNowDate());
        return crmOrderMapper.updateById(crmOrder);
    }

    /**
     * 批量删除订单
     *
     * @param orderIds 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteCrmOrderByOrderIds(Long[] orderIds) {
        return crmOrderMapper.deleteCrmOrderByOrderIds(orderIds);
    }

    /**
     * 删除订单信息
     *
     * @param orderId 订单主键
     * @return 结果
     */
    @Override
    public int deleteCrmOrderByOrderId(Long orderId) {
        return crmOrderMapper.deleteCrmOrderByOrderId(orderId);
    }

    @Override
    public int listeningOrder(JSONObject data, JSONObject extra, int status) {
        String id = data.getString("id");
        CrmOrder optOrder = Opt.ofNullable(crmOrderMapper.selectOne(Wrappers.<CrmOrder>lambdaQuery().eq(CrmOrder::getExternalOrderId, id))).orElse(null);
        /**
         * 140	140	订单已支付		"extra":{"type":1,//订单类型"storeId":"123456"//门店id}
         * 142	142	添加接种人		"extra":{"orderId":"163773xxxxxx82",//订单id "type":3,//订单类型，3:疫苗 "status":142,//订单状态 "storeId":161xxxxxxxxxx729,//门店id "storeName":"服务",//门店名称 "userName":"张三",//接种人姓名 "uploadTime":"2023-04-25 12:00:00", "changeType":0,//变更类型0：补充；1：修改 "appointmentType":10,//预约类型：10：分时预约 0：商家手动预约 "appointmentTime":"2023-04-25 上午"}
         * 190	190	订单已签收（物流）		"extra":{"signStatus":1,//签收状态1.签收2.拒收"deliverNo":"123456"//物流单号}
         * 191	143	已接单		"extra":{"type":1,//订单类型"storeId":"123456"//门店id}
         * 200	200	已签收（订单完结）		"extra": {}
         * 201	200	系统自动签收（订单完结）		"extra": {}
         * 130	130	交易关闭（订单完结）		"extra": {}
         */
        switch (status) {
            case 130:
                log.info("订单已取消");
                break;
            case 140:{
                log.info("订单已支付：{}", data);
                BaiDuJianKangApi.OrderDetailRequest orderDetailRequest = new BaiDuJianKangApi.OrderDetailRequest(data.getString("pfStoreId"), data.getString("id"));
                BaiDuJianKangApi.DataRequest<BaiDuJianKangApi.OrderDetailRequest> dataRequest = new BaiDuJianKangApi.DataRequest<BaiDuJianKangApi.OrderDetailRequest>(orderDetailRequest);
                String dataJson = JSON.toJSONString(dataRequest);
                JSONObject sendResult = BaiDuJianKangApi.send(apiCredentialProperties.getBaidus().get(0), null, BaiDuJianKangApi.ORDER_DETAIL, dataJson);
                log.info("请求结果:{}", sendResult);
                if (sendResult != null && sendResult.getIntValue("status", -1) == 0) {
                    BaiDuJianKangApi.OrderDetailResponse orderDetailResponse = sendResult.getObject("data", BaiDuJianKangApi.OrderDetailResponse.class);
                    BaiDuJianKangApi.GoodsResponse goodsResponse = orderDetailResponse.getGoods().get(0);
                    Integer execute = transactionTemplate.execute(ex -> {
                        List<OrderProductBo> orderProducts = orderDetailResponse.getGoods().stream().map(goods -> {
                            OrderProductBo productBo = new OrderProductBo();
                            productBo.setProductName(goods.getTitleName());
                            productBo.setProductTitle(goods.getTitleName());
                            productBo.setProductImage(goods.getHeadImgUrl());

                            productBo.setProductId(goods.getGoodsId());
                            productBo.setExternalProductId(goods.getGoodsId().toString());
                            productBo.setType(1);
                            productBo.setExternalType(0);
                            productBo.setNum(goods.getAmount());
                            productBo.setProductSpec(goods.getSpec());
                            productBo.setUnitNum(Convert.toInt(RegexpUtils.extractBoxNumber(goods.getSpec(), Constants.GOODS_UNITS)));
                            productBo.setTotalUnitNum(Convert.toInt((productBo.getUnitNum() / productBo.getNum()) * productBo.getNum()));
                            if (StringUtils.isNotEmpty(goods.getSellerDiscount())) {
                                Optional<BaiDuJianKangApi.GoodsResponse.SellerDiscount> first = goods.getSellerDiscount().stream().filter(f -> f.getType() == 2).findFirst();
                                if (first.isPresent()) {
                                    BaiDuJianKangApi.GoodsResponse.SellerDiscount sell = first.get();
                                    productBo.setExternalPackageId(sell.getId());
                                    productBo.setType(2);
                                    productBo.setExternalType(1);

                                    LambdaQueryWrapper<CrmProduct> wrapper = Wrappers.<CrmProduct>lambdaQuery().eq(CrmProduct::getExternalPackageId, sell.getId()).last("limit 1");
                                    CrmProduct crmProduct = crmProductMapper.selectOne(wrapper);
                                    if (crmProduct != null) {
                                        productBo.setProductName(crmProduct.getProductName());
                                        productBo.setProductTitle(crmProduct.getProductTitle());
                                        productBo.setProductSpec(crmProduct.getProductSpec());
                                        if (ObjUtil.isNotNull(crmProduct.getProductUnitNum())) {
                                            productBo.setUnitNum(crmProduct.getProductUnitNum());
                                            // 先求出规格对应数量的件数 在 乘以 商品数量 = 最终商品数量
                                            productBo.setTotalUnitNum(Convert.toInt((productBo.getUnitNum() / productBo.getNum()) * productBo.getNum()));
                                        }

                                    }
                                }
                            }
                            productBo.setProductPrice(new BigDecimal(goods.getPriceFen()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                            productBo.setActualPrice(new BigDecimal(goods.getUserPayment()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                            productBo.setOrderPrice(new BigDecimal(goods.getUserPayment() + goods.getDiscount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                            return productBo;
                        }).collect(Collectors.toList());
                        List<String> packageIds = orderProducts.stream().filter(f -> f.getExternalType() == 1).map(OrderProductBo::getExternalPackageId).collect(Collectors.toList());
                        log.info("订单详情: {}", JSON.toJSONString(orderDetailResponse));
                        String sn = RedisSnGenerator.build().getBusSn(RedisSnEnum.ORDER);
                        CrmOrder crmOrder = new CrmOrder();
                        crmOrder.setOrderId(IdWorker.getId());
                        crmOrder.setExternalOrderId(orderDetailResponse.getOrderId());
                        crmOrder.setStoreId(orderDetailResponse.getStoreId());
                        crmOrder.setStoreName(orderDetailResponse.getStoreName());
                        crmOrder.setUid(orderDetailResponse.getUserKey());
                        crmOrder.setOrderNo(sn);
                        crmOrder.setOrderStatus(orderDetailResponse.getStatus());
                        crmOrder.setProducts(JSONArray.parseArray(JSON.toJSONString(orderDetailResponse.getGoods())));
                        crmOrder.setProductName(goodsResponse.getTitleName());
                        crmOrder.setProductId(goodsResponse.getGoodsId());
                        crmOrder.setProductSpec(goodsResponse.getSpec());
                        crmOrder.setProductImg(goodsResponse.getHeadImgUrl());
                        crmOrder.setProductPrice(new BigDecimal(orderDetailResponse.getOriginalPriceFen()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                        crmOrder.setOrderPrice(new BigDecimal(orderDetailResponse.getGoodsPriceFen()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                        crmOrder.setActualPrice(new BigDecimal(orderDetailResponse.getUserPayment()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP));
                        crmOrder.setTotalAmount(crmOrder.getActualPrice());
                        crmOrder.setOrderQuantity(goodsResponse.getAmount());
                        crmOrder.setProductCollection(orderProducts);
                        crmOrder.setGroupProductIds(packageIds);
                        crmOrder.setReceiverName(orderDetailResponse.getReceName());
                        crmOrder.setReceiverPhone(orderDetailResponse.getReceMobile());
                        crmOrder.setReceiverAddress(StringUtils.format("{}{}{}{}", orderDetailResponse.getProvince(), orderDetailResponse.getCity(), orderDetailResponse.getDistrict(), orderDetailResponse.getReceAddressDetail()));
                        crmOrder.setOrderCount(0L);
                        crmOrder.setOrderTime(DateUtils.date(orderDetailResponse.getCreateTime()));
                        crmOrder.setPlatform("baidu");
                        crmOrder.setOrderType(1);
                        crmOrder.setChannelType(orderDetailResponse.getChannelType());
                        crmOrder.setChannelCode(orderDetailResponse.getChannelCode());
                        crmOrder.setUserRemark(String.join("|", new String[]{Opt.ofNullable(orderDetailResponse.getMessage()).orElse(""), Opt.ofNullable(orderDetailResponse.getRemark()).orElse("")}));
                        crmOrder.setPaymentName(orderDetailResponse.getPayName());

                        // 保存客户信息
                        CrmCustomer crmCustomer = saveCustomer(orderDetailResponse, crmOrder);
                        crmOrder.setCustomerId(crmCustomer.getCustomerId());

                        // 查询第几次下单
                        Long count = crmOrderMapper.selectCount(Wrappers.<CrmOrder>lambdaQuery().eq(CrmOrder::getCustomerId, crmCustomer.getCustomerId()).eq(CrmOrder::getOrderType, OrderType.SYSTEM.getType()));
                        crmOrder.setOrderCount(count + 1);

                        //  获取业务员信息,并绑定
                        CrmUserFollowRelation crmUserFollowRelation = crmUserFollowRelationMapper.selectOne(Wrappers.<CrmUserFollowRelation>lambdaQuery().eq(CrmUserFollowRelation::getCustomerId, crmCustomer.getCustomerId()));
                        if (ObjUtil.isNotNull(crmUserFollowRelation)) {
                            crmOrder.setSalesmanId(crmUserFollowRelation.getUserId());
                            SysUser sysUser = sysUserMapper.selectUserById(crmOrder.getSalesmanId());
                            crmOrder.setSalesmanName(Opt.ofNullable(sysUser).map(SysUser::getUserName).orElse(null));
                        }
                        // 去异步发货
                        int insert = crmOrderMapper.insert(crmOrder);
                        if (insert > 0) {

                            // DelaySaverService.orderShipping.publishAsync(crmOrder.getOrderId().toString(), 2);

                            if (count == 0){
                                try {
                                    LogisticsShippingRequest shippingRequest = new LogisticsShippingRequest();
                                    shippingRequest.setOrderId(crmOrder.getOrderId());
                                    shippingRequest.setShippingType(1);
                                    shippingRequest.setLogisticsPlatformCode(ExpressCompanyEnum.JINGDONGKUAIYUN.getCode());
                                    this.logisticsShipping(shippingRequest);
                                } catch (Exception e) {
                                    log.error("订单发货异常", e);
                                }
                            }

                            SysNotice sysNotice = SysNotice.builder()
                                    .noticeTitle("有新订单")
                                    .noticeType("1")
                                    .noticeContent("订单：" + crmOrder.getOrderNo() + "已下单,请注意分配业务员！")
                                    .sendId(0L)
                                    .roleCode(RoleEnum.CUSTOMER_SERVICE.getRoleCode())
                                    .msgType(MsgType.ORDINARY.getValue()).build();
                            SpringUtil.publishEvent(sysNotice);
                        }
                        return insert;
                    });
                }else {
                    log.error("订单异常：{}", data);
                    throw new ServiceException("订单异常");
                }
                break;
            }
            case 190:
                log.info("订单已签收（物流）：{}", data);
                break;
            case 143:
                log.info("已接单：{}", data);
                break;
            case 200:
            case 201:
                status = 200;
                log.info("已签收（订单完结）：{}", data);
                break;
        }
        int finalStatus = status;

        if (finalStatus != 140) {

            RedisUtils.builder().redissonLock(RedisConstants.ORDER_PREFIX + id, TimeUnit.SECONDS, 3, 3, () -> {
                CrmLogisticsRecord crmLogisticsRecord = new CrmLogisticsRecord();
                LambdaUpdateWrapper<CrmOrder> wrapper = Wrappers.<CrmOrder>lambdaUpdate()
                        .set(CrmOrder::getOrderStatus, finalStatus)
                        .eq(CrmOrder::getExternalOrderId, id);
                if (Arrays.asList(200, 201).contains(finalStatus)){
                    wrapper.set(CrmOrder::getOrderStatus, CrmOrderStatus.COMPLETED.getCode());
                }
                if (Arrays.asList(190, 200, 201).contains(finalStatus)) {
                    BaiDuJianKangApi.OrderDetailRequest orderDetailRequest = new BaiDuJianKangApi.OrderDetailRequest(data.getString("storeId"), data.getString("id"));
                    BaiDuJianKangApi.DataRequest<BaiDuJianKangApi.OrderDetailRequest> dataRequest = new BaiDuJianKangApi.DataRequest<BaiDuJianKangApi.OrderDetailRequest>(orderDetailRequest);
                    String dataJson = JSON.toJSONString(dataRequest);
                    JSONObject sendResult = BaiDuJianKangApi.send(apiCredentialProperties.getBaidus().get(0), null, BaiDuJianKangApi.ORDER_DETAIL, dataJson);
                    log.info("请求结果:{}", sendResult);
                    if (sendResult != null && sendResult.getIntValue("status", -1) == 0) {
                        BaiDuJianKangApi.OrderDetailResponse orderDetailResponse = sendResult.getObject("data", BaiDuJianKangApi.OrderDetailResponse.class);
                        wrapper.set(CrmOrder::getLogisticsPlatform, orderDetailResponse.getDeliverName());
                        wrapper.set(CrmOrder::getLogisticsNo, orderDetailResponse.getDeliverNo());

                        JSONArray deliverInfos = sendResult.getJSONArray("deliverInfos");
                        if (ObjUtil.isNotEmpty(deliverInfos)) {
                            JSONObject jsonObject = deliverInfos.getJSONObject(0);
                            String objectString = jsonObject.getString("description");
                            wrapper.set(CrmOrder::getLogisticsProgress, objectString);
                        }


                        int signStatus = Opt.ofNullable(extra).map(m -> m.getIntValue("signStatus", 0)).orElse(0);

                        if (finalStatus == 190){
                            if (ObjUtil.isNotEmpty(optOrder)){
                                CrmLogisticsRecord logisticsRecord = new CrmLogisticsRecord();
                                logisticsRecord.setExternalOrderId(optOrder.getExternalOrderId());
                                logisticsRecord.setLogisticsNo(orderDetailResponse.getDeliverNo());
                                logisticsRecord.setLogisticsCompany(orderDetailResponse.getDeliverName());
                                logisticsRecord.setOrderId(optOrder.getOrderId());
                                logisticsRecord.setReceiverAddress(optOrder.getReceiverAddress());
                                logisticsRecord.setReceiverName(optOrder.getReceiverName());
                                logisticsRecord.setReceiverPhone(optOrder.getReceiverPhone());
                                logisticsRecord.setLogisticsStatus(Opt.ofNullable(new Integer[]{null,1,2}[signStatus]).map(Object::toString).orElse(null));
                                logisticsRecord.setRemark(optOrder.getUserRemark());
                                logisticsRecord.setLogisticsCode(ExpressCompanyEnum.getByName(logisticsRecord.getLogisticsCompany()).getCode());

                                if (crmLogisticsRecordMapper.selectCount(Wrappers.lambdaQuery(CrmLogisticsRecord.class).eq(CrmLogisticsRecord::getExternalOrderId, optOrder.getExternalOrderId())) > 0) {
                                    crmLogisticsRecordMapper.update(logisticsRecord, Wrappers.lambdaQuery(CrmLogisticsRecord.class).eq(CrmLogisticsRecord::getExternalOrderId, optOrder.getExternalOrderId()));
                                }else {
                                    crmLogisticsRecordMapper.insert(logisticsRecord);
                                }
                            }
                        }


                        if (signStatus != 0) {
                            crmLogisticsRecord.setLogisticsStatus(signStatus + "");
                            wrapper.set(CrmOrder::getLogisticsStatus, signStatus);
                            wrapper.set(CrmOrder::getLogisticsProgress, new String[]{"", "已签收", "拒收"}[finalStatus]);
                            wrapper.set(CrmOrder::getLogisticsSignTime, DateUtils.date().toJdkDate());
                            if (signStatus == 2) {
                                Opt<CrmOrder> crmOrderOpt = Opt.ofNullable(crmOrderMapper.selectOne(Wrappers.<CrmOrder>lambdaQuery().eq(CrmOrder::getExternalOrderId, id)));
                                crmOrderOpt.ifPresent(crmOrder -> {
                                    SysNotice sysNotice = SysNotice.builder()
                                            .noticeTitle("订单拒签")
                                            .noticeType("1")
                                            .noticeContent("订单：" + crmOrder.getOrderNo() + "已拒签,请注意跟进！")
                                            .sendId(0L)
                                            .userId(crmOrder.getSalesmanId())
                                            .msgType(MsgType.RECEIPTED.getValue()).build();
                                    SpringUtil.publishEvent(sysNotice);
                                });
                            }
                            if (signStatus == 1) {
                                if (ObjUtil.isNotEmpty(optOrder)){
                                    if (!optOrder.getLogisticsStatus().equals(LogisticsStatus.SIGNED.getCode())) {
                                        List<CrmProductStockRecord> records = optOrder.getProductCollection().parallelStream().map(item -> {
                                            CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                                            crmProductStockRecord.setOperationType(2);
                                            crmProductStockRecord.setOrderId(optOrder.getOrderId());
                                            crmProductStockRecord.setProductId(item.getProductId());
                                            crmProductStockRecord.setOrderStatus(1);
                                            crmProductStockRecord.setChangeQuantity(Convert.toLong(item.getNum()) / item.getUnitNum());
                                            return crmProductStockRecord;
                                        }).toList();
                                        crmProductStockRecordMapper.insert(records);

                                        SysNotice sysNotice = SysNotice.builder()
                                                .noticeTitle("订单签收成功")
                                                .noticeType("1")
                                                .noticeContent("订单：" + optOrder.getOrderNo() + "已签收,请注意跟进！")
                                                .sendId(0L)
                                                .userId(optOrder.getSalesmanId())
                                                .msgType(MsgType.RECEIPTED.getValue()).build();
                                        SpringUtil.publishEvent(sysNotice);
                                    }
                                }
                             }
                        } else if (Arrays.asList(200, 201).contains(finalStatus)) {
                            wrapper.set(CrmOrder::getLogisticsStatus, 1);
                            wrapper.set(CrmOrder::getLogisticsProgress, "已签收");
                            wrapper.set(CrmOrder::getLogisticsSignTime, DateUtils.date().toJdkDate());
                            crmLogisticsRecord.setLogisticsStatus("1");

                            if (ObjUtil.isNotEmpty(optOrder)){
                                if (!optOrder.getLogisticsStatus().equals(LogisticsStatus.SIGNED.getCode())) {
                                    List<CrmProductStockRecord> records = optOrder.getProductCollection().parallelStream().map(item -> {
                                        CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                                        crmProductStockRecord.setOperationType(2);
                                        crmProductStockRecord.setOrderId(optOrder.getOrderId());
                                        crmProductStockRecord.setProductId(item.getProductId());
                                        crmProductStockRecord.setOrderStatus(1);
                                        crmProductStockRecord.setChangeQuantity(Convert.toLong(item.getNum()) / item.getUnitNum());
                                        return crmProductStockRecord;
                                    }).toList();
                                    crmProductStockRecordMapper.insert(records);

                                    SysNotice sysNotice = SysNotice.builder()
                                            .noticeTitle("订单签收成功")
                                            .noticeType("1")
                                            .noticeContent("订单：" + optOrder.getOrderNo() + "已签收,请注意跟进！")
                                            .sendId(0L)
                                            .userId(optOrder.getSalesmanId())
                                            .msgType(MsgType.RECEIPTED.getValue()).build();
                                    SpringUtil.publishEvent(sysNotice);
                                }
                            }
                        }

                        if (ObjUtil.isNotEmpty(crmLogisticsRecord.getLogisticsStatus())) {
                            crmLogisticsRecordMapper.update(crmLogisticsRecord, Wrappers.lambdaQuery(CrmLogisticsRecord.class).eq(CrmLogisticsRecord::getExternalOrderId, id));
                        }

                    }else {
                        log.error("订单信息查询失败：{},请求结果：{}", dataJson, sendResult);
                    }

                }
                return crmOrderMapper.update(wrapper);
            }, "订单处理中...");
            log.info("订单处理完成,状态：{}", status);
        }

        return 0;
    }

    /**
     * 分配业务员
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String assignSalesman(AssignSalesmanRequest request) {
        StringBuilder sb = new StringBuilder();

        SysUser sysUser = sysUserMapper.selectUserById(request.getSalesmanId());
        if (sysUser == null) {
            throw new ServiceException("业务员不存在");
        }
        request.getIds().forEach(orderId -> {
            try {
                CrmOrder crmOrder = crmOrderMapper.selectById(orderId);
                if (crmOrder == null) {
                    throw new ServiceException(String.format("订单不存在：%s", orderId));
                }
                if (ObjUtil.isEmpty(crmOrder.getCustomerId())) {
                    throw new ServiceException(StrUtil.format("订单:{},客户不存在", orderId));
                }
                if (crmOrder.getSalesmanId() != null) {
                    throw new ServiceException(StrUtil.format("订单:{},已分配：{}", orderId, crmOrder.getSalesmanName()));
                }
                CrmCustomer crmCustomer = crmCustomerMapper.selectById(crmOrder.getCustomerId());
                if (crmCustomer == null) {
                    throw new ServiceException(String.format("客户不存在：%s", crmOrder.getCustomerId()));
                }

                LambdaQueryWrapper<CrmUserFollowRelation> wrapper = Wrappers.<CrmUserFollowRelation>lambdaQuery()
                        .eq(CrmUserFollowRelation::getCustomerId, crmOrder.getCustomerId())
                        .last("limit 1");
                CrmUserFollowRelation userFollowRelation = crmUserFollowRelationMapper.selectOne(wrapper);
                if (userFollowRelation != null) {
                    throw new ServiceException(StrUtil.format("订单:{},已分配业务员", orderId));
                }

                RedisUtils.builder().redissonLock(RedisConstants.LOCK_PREFIX + request.getSalesmanId(), () -> {
                    CrmUserFollowRelation crmUserFollowRelation = new CrmUserFollowRelation();
                    crmUserFollowRelation.setUserId(sysUser.getUserId());
                    crmUserFollowRelation.setOrderId(orderId);
                    crmUserFollowRelation.setCustomerId(crmOrder.getCustomerId());
                    crmUserFollowRelation.setDeptId(sysUser.getDeptId());
                    crmUserFollowRelation.setExternalOrderId(crmOrder.getExternalOrderId());
                    crmUserFollowRelation.setFollowUpStatus(0);
                    crmUserFollowRelationMapper.insert(crmUserFollowRelation);

                    CrmCustomer customer = new CrmCustomer();
                    customer.setCustomerId(crmCustomer.getCustomerId());
                    customer.setSalesmanId(sysUser.getUserId());
                    crmCustomerMapper.updateById(customer);

                    CrmOrder updateCrmOrder = new CrmOrder();
                    updateCrmOrder.setShippingType(request.getShippingType());
                    updateCrmOrder.setSalesmanId(sysUser.getUserId());
                    updateCrmOrder.setOrderId(orderId);
                    updateCrmOrder.setSalesmanName(sysUser.getNickName());
                    updateCrmOrder.setOrderRemark(request.getRemark());
                    return crmOrderMapper.updateById(updateCrmOrder);
                }, StrUtil.format("订单：{},分配业务员已在处理中...", orderId));

                SysNotice sysNotice = SysNotice.builder()
                        .noticeTitle("订单分配成功")
                        .noticeType("1")
                        .noticeContent(StrUtil.format("客户姓名：{},订单编号：{}已分配,请注意跟进！", crmCustomer.getCustomerName(), crmOrder.getOrderNo()))
                        .sendId(SecurityUtils.getUserId())
                        .userId(sysUser.getUserId())
                        .msgType(MsgType.ORDINARY.getValue()).build();
                SpringUtil.publishEvent(sysNotice);
            } catch (ServiceException e) {
                sb.append(e.getMessage()).append(";");
            }
        });
        return sb.toString();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LogisticsOrderBo  logisticsShipping(LogisticsShippingRequest request) {
        CrmOrder crmOrder = crmOrderMapper.selectById(request.getOrderId());
        if (crmOrder == null) {
            throw new ServiceException("订单不存在");
        }
        if (crmOrder.getOrderStatus() != 140) {
            throw new ServiceException("订单已分配");
        }
        if (StringUtils.isNotEmpty(crmOrder.getLogisticsNo())) {
            throw new ServiceException("订单已分配");
        }

        if (crmOrder.getIsChildren() == 1) {
            throw new ServiceException("子订单不允许分配");
        } else if (ObjUtil.isNotEmpty(crmOrder.getPackageIds())) {
            List<CrmOrder> crmOrders = crmOrderMapper.selectList(Wrappers.<CrmOrder>lambdaQuery().in(CrmOrder::getOrderId, crmOrder.getPackageIds().toList(Long.class)));
            crmOrder.setChildrens(crmOrders);
        }

        LogisticsOrderBo logisticsOrderBo = null;
        Integer shippingType = Opt.ofNullable(request.getShippingType()).or(() -> Opt.ofNullable(crmOrder.getShippingType())).orElseThrow();
        // 系统发货
        if (Objects.equals(shippingType, ShippingType.SYSTEM_SHIPPING.getType())) {

            Opt<SysUser> sysUserOpt = Opt.ofNullable(crmOrder.getSalesmanId()).map(id -> sysUserMapper.selectUserById(crmOrder.getSalesmanId()));

            logisticsOrderBo = RedisUtils.builder().redissonLock(RedisConstants.ORDER_PREFIX + request.getOrderId(), () -> {
                CommonCargoInfoBo cargoInfoBo = new CommonCargoInfoBo();
                cargoInfoBo.setName("易碎物品");
                cargoInfoBo.setRemark(StrUtil.format(sysUserOpt.map(SysUser::getPrintStr).orElse("易碎物品!") + "{}", crmOrder.getTotalAmount().toPlainString()));
                cargoInfoBo.setQuantity(1);
                if (crmOrder.getOrderType() == 2){
                    int size = Opt.ofNullable(crmOrder.getPackageIds()).map(JSONArray::size).orElse(1);
                    cargoInfoBo.setQuantity(size);
                }
                return jdLogisticsService.orderCreate(crmOrder, cargoInfoBo);
            }, StrUtil.format("订单：{},物流配送已在处理中...", request.getOrderId()));

            if (crmOrder.getOrderType() == 1){
                BaiDuJianKangApi.AddDeliverListRequest addDeliverListRequest = new BaiDuJianKangApi.AddDeliverListRequest();
                addDeliverListRequest.setOrderId(crmOrder.getExternalOrderId());
                addDeliverListRequest.setDeliverName(logisticsOrderBo.getLogisticsPlatformCode());
                addDeliverListRequest.setDeliverNo(crmOrder.getLogisticsNo());
                addDeliverListRequest.setStoreId(RegexpUtils.extractNumber(crmOrder.getStoreId()).toString());
                addDeliverListRequest.setDeliverBatch(new ArrayList<>());
                BaiDuJianKangApi.DataRequest<List<BaiDuJianKangApi.AddDeliverListRequest>> dataRequest = new BaiDuJianKangApi.DataRequest<>(Arrays.asList(addDeliverListRequest));
                String dataJson = JSON.toJSONString(dataRequest);
                log.info("请求参数：{}", dataJson);
                JSONObject sendResult = BaiDuJianKangApi.send( apiCredentialProperties.getBaidus().get(0),null, BaiDuJianKangApi.ADD_DELIVER_LIST, dataJson);
                log.info("请求结果:{}", sendResult);
                if (sendResult != null && sendResult.getIntValue("status", -1) == 0) {
                    List<BaiDuJianKangApi.DeliverResponse> deliverResponses = sendResult.getJSONArray("data").toList(BaiDuJianKangApi.DeliverResponse.class);
                    log.info("货运详情: {}", deliverResponses);
                    CrmOrder updateOrder = new CrmOrder();
                    updateOrder.setOrderId(crmOrder.getOrderId());
                    updateOrder.setShippingType(request.getShippingType());
                    updateOrder.setLogisticsStatus(logisticsOrderBo.getLogisticsStatus());
                    updateOrder.setLogisticsNo(logisticsOrderBo.getLogisticsNo());
                    if (StrUtil.isNotBlank(request.getLogisticsPlatformCode())){
                        updateOrder.setLogisticsPlatformCode(request.getLogisticsPlatformCode());
                        updateOrder.setLogisticsPlatform(ExpressCompanyEnum.getByCode(request.getLogisticsPlatformCode()).getName());
                    }
                    updateOrder.setLogisticsProgress("待揽收");
                    this.updateById(updateOrder);
                }else {
                    log.error("发货请求失败:{}", sendResult);
                    throw new ServiceException("请求失败");
                }
            }


            CrmOrder updateOrder = new CrmOrder();
            updateOrder.setOrderId(crmOrder.getOrderId());
            updateOrder.setShippingType(crmOrder.getShippingType());
            updateOrder.setLogisticsPlatformCode(crmOrder.getLogisticsPlatformCode());
            updateOrder.setLogisticsPlatform(ExpressCompanyEnum.getByCode(logisticsOrderBo.getLogisticsPlatformCode()).getName());
            updateOrder.setLogisticsStatus("3");
            updateOrder.setOrderStatus(150);
            updateOrder.setLogisticsProgress("待揽收");
            updateOrder.setLogisticsNo(crmOrder.getLogisticsNo());
            this.updateById(updateOrder);
        }else if (Objects.equals(shippingType, ShippingType.SELF_SHIPPING.getType())) { // 自主发货
            CrmOrder updateOrder = new CrmOrder();
            updateOrder.setOrderId(crmOrder.getOrderId());
            updateOrder.setShippingType(shippingType);
            if (StrUtil.isBlank(request.getLogisticsPlatformCode())) {
                throw new ServiceException("请选择物流平台");
            }
            if (StrUtil.isBlank(request.getLogisticsNo())) {
                throw new ServiceException("请填写物流单号");
            }
            updateOrder.setLogisticsPlatformCode(request.getLogisticsPlatformCode());
            updateOrder.setLogisticsPlatform(ExpressCompanyEnum.getByCode(request.getLogisticsPlatformCode()).getName());
            updateOrder.setLogisticsStatus("3");
            updateOrder.setOrderStatus(150);
            updateOrder.setLogisticsProgress("已发货");
            updateOrder.setLogisticsNo(request.getLogisticsNo());
            this.updateById(updateOrder);

            CrmLogisticsRecord crmLogisticsRecord = new CrmLogisticsRecord();
            crmLogisticsRecord.setOrderId(crmOrder.getOrderId());
            crmLogisticsRecord.setExternalOrderId(crmOrder.getExternalOrderId());
            crmLogisticsRecord.setReceiverName(crmOrder.getReceiverName());
            crmLogisticsRecord.setReceiverAddress(crmOrder.getReceiverAddress());
            crmLogisticsRecord.setReceiverPhone(crmOrder.getReceiverPhone());
            crmLogisticsRecord.setLogisticsNo(crmOrder.getLogisticsNo());
            crmLogisticsRecord.setLogisticsStatus(crmOrder.getLogisticsStatus());
            crmLogisticsRecordMapper.insert(crmLogisticsRecord);

            logisticsOrderBo = new LogisticsOrderBo();
            logisticsOrderBo.setLogisticsStatus(crmOrder.getLogisticsStatus());
            logisticsOrderBo.setLogisticsNo(updateOrder.getLogisticsNo());
            logisticsOrderBo.setLogisticsPlatform(updateOrder.getLogisticsPlatform());
            logisticsOrderBo.setLogisticsPlatformCode(updateOrder.getLogisticsPlatformCode());
            logisticsOrderBo.setSysLogisticsOrderId(crmOrder.getOrderNo());
            logisticsOrderBo.setSysOrderId(crmOrder.getOrderId());
            logisticsOrderBo.setSysExternalOrderId(crmOrder.getExternalOrderId());
        }
        return logisticsOrderBo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public LogisticsOrderBo logisticsCancel(LogisticsCancelRequest request) {
        CrmOrder crmOrder = crmOrderMapper.selectById(request.getOrderId());
        if (crmOrder == null) {
            throw new ServiceException("订单不存在");
        }
        if (ObjUtil.isEmpty(crmOrder.getLogisticsNo())) {
            throw new ServiceException("订单物无物流单号");
        }
        LogisticsOrderBo orderCancel = jdLogisticsService.orderCancel(crmOrder);
        // 物流状态（0 待发货 1已签收 2拒绝签收 3已发货,4取消，5拦截中，6拦截成功）
        String logisticsStatus = orderCancel.getLogisticsStatus();
        if (Arrays.asList("4", "6").contains(logisticsStatus)) {
            LambdaUpdateWrapper<CrmOrder> wrapper = Wrappers.<CrmOrder>lambdaUpdate()
                    .set(CrmOrder::getLogisticsStatus, logisticsStatus)
                    // .set(CrmOrder::getLogisticsNo,null)
                    .set(CrmOrder::getLogisticsProgress, "已取消")
                    .set(CrmOrder::getOrderStatus, CrmOrderStatus.CANCELED.getCode())
                    .eq(CrmOrder::getOrderId, crmOrder.getOrderId());
            int update = crmOrderMapper.update(wrapper);
            if (update > 0 && Objects.equals(crmOrder.getOrderType(), OrderType.REPURCHASE.getType())) {
                AsyncManager.me().execute(() -> {
                    if (ObjUtil.isNotEmpty(crmOrder.getPackageIds())) {
                        crmOrderMapper.selectList(Wrappers.<CrmOrder>lambdaQuery().select(CrmOrder::getProductCollection).eq(CrmOrder::getRelatedOrderId,crmOrder.getOrderId())).forEach(item->{
                            item.getProductCollection().forEach(mm->{
                                CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                                crmProductStockRecord.setProductId(mm.getProductId());
                                crmProductStockRecord.setOrderId(item.getOrderId());
                                crmProductStockRecord.setOrderStatus(3);
                                crmProductStockRecord.setChangeQuantity(Convert.toLong(mm.getNum()));
                                crmProductService.stockOperation(crmProductStockRecord, OperationTypeEnum.ADD);
                            });
                        });
                    }else {
                        crmOrder.getProductCollection().forEach(mm->{
                            CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                            crmProductStockRecord.setProductId(mm.getProductId());
                            crmProductStockRecord.setOrderId(crmOrder.getOrderId());
                            crmProductStockRecord.setOrderStatus(3);
                            crmProductStockRecord.setChangeQuantity(Convert.toLong(mm.getNum()));
                            crmProductService.stockOperation(crmProductStockRecord, OperationTypeEnum.ADD);
                        });
                    }
                    return Boolean.TRUE;
                });
            }
        }
        return orderCancel;
    }
    /**
     * 添加复购
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addRepurchase(AddRepurchaseOrderRequest request) {
        CrmOrder crmOrder = BeanUtil.copyProperties(request, CrmOrder.class);
        crmOrder.setOrderType(2);
        crmOrder.setOrderId(IdWorker.getId());

        // 获取销售人员,并绑定
        LambdaQueryWrapper<CrmUserFollowRelation> wrapper = Wrappers.<CrmUserFollowRelation>lambdaQuery()
                .eq(CrmUserFollowRelation::getCustomerId, request.getCustomerId())
                .last("limit 1");
        CrmUserFollowRelation userFollowRelation = crmUserFollowRelationMapper.selectOne(wrapper);
        if(userFollowRelation != null) {
            crmOrder.setSalesmanId(userFollowRelation.getUserId());
            SysUser sysUser = sysUserMapper.selectUserById(userFollowRelation.getUserId());
            crmOrder.setSalesmanName(sysUser.getNickName());
        }
        Long count = crmOrderMapper.selectCount(Wrappers.<CrmOrder>lambdaQuery().eq(CrmOrder::getCustomerId, crmOrder.getCustomerId()).eq(CrmOrder::getOrderType, crmOrder.getOrderType()));
        crmOrder.setOrderCount(count + 1);
        crmOrder.setOrderStatus(140);
        if (StringUtils.isNotBlank(request.getLogisticsPlatformCode())){
            crmOrder.setLogisticsPlatformCode(request.getLogisticsPlatformCode());
            crmOrder.setLogisticsPlatform(ExpressCompanyEnum.getByCode(request.getLogisticsPlatformCode()).getName());
        }
        if (StringUtils.isNotBlank(request.getLogisticsNo())) {
            crmOrder.setLogisticsStatus("3");
            crmOrder.setOrderStatus(150);
            crmOrder.setLogisticsProgress("已发货");
        }

        crmOrder.getProductCollection().parallelStream().forEach(item -> {
            CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
            crmProductStockRecord.setProductId(item.getProductId());
            crmProductStockRecord.setOrderId(crmOrder.getOrderId());
            crmProductStockRecord.setOrderStatus(1);
            crmProductStockRecord.setChangeQuantity(Convert.toLong(item.getNum()));
            crmProductService.stockOperation(crmProductStockRecord, OperationTypeEnum.REDUCE);
        });

        String sn = RedisSnGenerator.build().getBusSn(RedisSnEnum.REPURCHASE_ORDER);
        crmOrder.setOrderNo(sn);

        int insert = crmOrderMapper.insert(crmOrder);
        if (insert > 0) {
            jdLogisticsService.traceSubscribe(crmOrder);
        }
        return commShipping(crmOrder, insert);


    }

    /**
     * 添加复购
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addRepurchases(AddsRepurchaseOrderRequest request) {
        CrmOrder crmOrder = BeanUtil.copyProperties(request, CrmOrder.class);
        crmOrder.setOrderType(2);
        crmOrder.setOrderStatus(140);
        crmOrder.setOrderId(IdWorker.getId());
        crmOrder.setIsMultiPackage(1);
        crmOrder.setOrderTime(Opt.ofNullable(request.getOrderTime()).orElse(DateUtils.date().toJdkDate()));
        if (StringUtils.isNotBlank(request.getLogisticsPlatformCode())){
            crmOrder.setLogisticsPlatformCode(request.getLogisticsPlatformCode());
            crmOrder.setLogisticsPlatform(ExpressCompanyEnum.getByCode(request.getLogisticsPlatformCode()).getName());
        }
        if (StringUtils.isNotBlank(request.getLogisticsNo())) {
            crmOrder.setLogisticsStatus("3");
            crmOrder.setLogisticsProgress("已发货");
            crmOrder.setOrderStatus(150);
        }
        LambdaQueryWrapper<CrmUserFollowRelation> wrapper = Wrappers.<CrmUserFollowRelation>lambdaQuery()
                .eq(CrmUserFollowRelation::getCustomerId, request.getCustomerId())
                .last("limit 1");
        CrmUserFollowRelation userFollowRelation = crmUserFollowRelationMapper.selectOne(wrapper);
        if(userFollowRelation != null) {
            crmOrder.setSalesmanId(userFollowRelation.getUserId());
            SysUser sysUser = sysUserMapper.selectUserById(userFollowRelation.getUserId());
            crmOrder.setSalesmanName(sysUser.getNickName());
        }
        Long count = crmOrderMapper.selectCount(Wrappers.<CrmOrder>lambdaQuery().eq(CrmOrder::getCustomerId, crmOrder.getCustomerId()).eq(CrmOrder::getOrderType, crmOrder.getOrderType()));
        crmOrder.setOrderCount(count + 1);
        List<CrmOrder> crmOrders = request.getPackages().stream().map(order -> {
            CrmOrder crmOrderChild = BeanUtil.copyProperties(order, CrmOrder.class);
            crmOrderChild.setOrderId(IdWorker.getId());
            crmOrderChild.setOrderType(crmOrder.getOrderType());
            crmOrderChild.setIsMultiPackage(crmOrder.getIsMultiPackage());
            crmOrderChild.setOrderCount(crmOrder.getOrderCount());
            crmOrderChild.setOrderStatus(crmOrder.getOrderStatus());
            crmOrderChild.setLogisticsStatus(crmOrder.getLogisticsStatus());
            crmOrderChild.setLogisticsProgress(crmOrder.getLogisticsProgress());
            crmOrderChild.setLogisticsNo(crmOrder.getLogisticsNo());
            crmOrderChild.setLogisticsPlatformCode(crmOrder.getLogisticsPlatformCode());
            crmOrderChild.setLogisticsPlatform(crmOrder.getLogisticsPlatform());
            crmOrderChild.setSalesmanId(crmOrder.getSalesmanId());
            crmOrderChild.setSalesmanName(crmOrder.getSalesmanName());
            crmOrderChild.setPlatform(crmOrder.getPlatform());

            crmOrderChild.getProductCollection().parallelStream().forEach(item -> {
                CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                crmProductStockRecord.setProductId(item.getProductId());
                crmProductStockRecord.setOrderId(crmOrder.getOrderId());
                crmProductStockRecord.setOrderStatus(1);
                crmProductStockRecord.setChangeQuantity(Convert.toLong(item.getNum()));
                crmProductService.stockOperation(crmProductStockRecord, OperationTypeEnum.REDUCE);
            });

            String sn = RedisSnGenerator.build().getBusSn(RedisSnEnum.REPURCHASE_ORDER);
            crmOrderChild.setOrderNo(sn);
            crmOrderChild.setRelatedOrderId(crmOrder.getOrderId().toString());
            crmOrderChild.setIsChildren(1);
            return crmOrderChild;
        }).toList();
        List<Long> packageIds = crmOrders.stream().map(CrmOrder::getOrderId).toList();
        crmOrders.stream().map(CrmOrder::getActualPrice).reduce(BigDecimal::add).ifPresent(crmOrder::setActualPrice);
        crmOrders.stream().map(CrmOrder::getTotalAmount).reduce(BigDecimal::add).ifPresent(crmOrder::setTotalAmount);
        crmOrders.stream().map(CrmOrder::getCodAmount).reduce(BigDecimal::add).ifPresent(crmOrder::setCodAmount);
        crmOrder.setPackageIds(JSONArray.from(packageIds));
        String sn = RedisSnGenerator.build().getBusSn(RedisSnEnum.REPURCHASE_ORDER);
        crmOrder.setOrderNo(sn);
        this.saveBatch(crmOrders);
        int insert = crmOrderMapper.insert(crmOrder);
        if (insert > 0) {
            jdLogisticsService.traceSubscribe(crmOrder);
        }
        return commShipping(crmOrder, insert);
    }

    @Override
    public int orderTop(OrderTopRequest request) {
        if (ObjUtil.isAllEmpty(request.getCTopType(),request.getTopType())){
            throw new ServiceException("请选择置顶类型");
        }
        LambdaUpdateWrapper<CrmOrder> wrapper = Wrappers.<CrmOrder>lambdaUpdate();
        wrapper.eq(CrmOrder::getOrderId, request.getOrderId());
        CrmOrder crmOrder = BeanUtil.copyProperties(request, CrmOrder.class);
        if(ObjUtil.isNotEmpty(request.getTopStatus())){
            if("1".equals(request.getTopStatus())){
                crmOrder.setTopTime(DateUtils.getNowDate());
            }else {
                wrapper.set(CrmOrder::getTopTime, null);
                wrapper.set(CrmOrder::getTopType, null);
            }
        }
        if(ObjUtil.isNotEmpty(request.getCTopStatus())){
            if("1".equals(request.getCTopStatus())){
                crmOrder.setCTopTime(DateUtils.getNowDate());
            }else {
                wrapper.set(CrmOrder::getCTopTime, null);
                wrapper.set(CrmOrder::getCTopType, null);
            }
        }
        return baseMapper.update(crmOrder, wrapper);
    }

    /**
     * 添加补货单
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int addReplenishment(AddReplenishmentOrderRequest request) {
        CrmOrder crmOrder = this.getById(request.getRelatedOrderId());
        if (crmOrder == null) {
            throw new ServiceException("订单不存在");
        }

        CrmOrder updateOrder = new CrmOrder();
        updateOrder.setOrderId(IdWorker.getId());
        updateOrder.setRelatedOrderId(request.getRelatedOrderId());
        updateOrder.setShippingType(request.getShippingType());
        updateOrder.setOrderType(2);
        updateOrder.setOrderStatus(140);
        updateOrder.setIsReplenishOrder(1);
        updateOrder.setSalesmanId(crmOrder.getSalesmanId());
        updateOrder.setSalesmanName(crmOrder.getSalesmanName());
        updateOrder.setCustomerId(crmOrder.getCustomerId());
        updateOrder.setReplenishOrderType(request.getReplenishOrderType());
        updateOrder.setReceiverName(crmOrder.getReceiverName());
        updateOrder.setReceiverPhone(crmOrder.getReceiverPhone());
        updateOrder.setReceiverAddress(crmOrder.getReceiverAddress());
        updateOrder.setPaymentMethod(crmOrder.getPaymentMethod());
        updateOrder.setPaymentName(crmOrder.getPaymentName());
        updateOrder.setProductCollection(request.getProductCollection());
        updateOrder.setOrderCount(crmOrder.getOrderCount());
        updateOrder.setIsDelayedDelivery(request.getIsDelayedDelivery());
        updateOrder.setIsFixed(request.getIsFixed());
        updateOrder.setIsBigOrder(request.getIsBigOrder());
        updateOrder.setCodAmount(request.getCodAmount());
        updateOrder.setOrderPrice(request.getOrderPrice());
        updateOrder.setActualPrice(request.getActualPrice());
        updateOrder.setTotalAmount(request.getTotalAmount());
        updateOrder.setTransferOrderAmount(request.getTransferOrderAmount());
        updateOrder.setPlatform(request.getPlatform());
        updateOrder.setOrderRemark(request.getOrderRemark());
        updateOrder.setOrderTime(Opt.ofNullable(request.getOrderTime()).orElse(DateUtils.date().toJdkDate()));
        updateOrder.setCreateTime(null);
        updateOrder.setCreateBy(null);
        Long count = crmOrderMapper.selectCount(Wrappers.<CrmOrder>lambdaQuery().eq(CrmOrder::getCustomerId, crmOrder.getCustomerId()).eq(CrmOrder::getOrderType, crmOrder.getOrderType()));
        crmOrder.setOrderCount(count + 1);


        String sn = RedisSnGenerator.build().getBusSn(RedisSnEnum.REPURCHASE_ORDER);
        updateOrder.setOrderNo(sn);
        if (StringUtils.isNotBlank(request.getLogisticsPlatformCode())){
            updateOrder.setLogisticsPlatformCode(request.getLogisticsPlatformCode());
            updateOrder.setLogisticsPlatform(ExpressCompanyEnum.getByCode(request.getLogisticsPlatformCode()).getName());
        }
        if (StringUtils.isNotBlank(request.getLogisticsNo())) {
            updateOrder.setLogisticsStatus("3");
            updateOrder.setLogisticsProgress("已发货");
            updateOrder.setOrderStatus(150);
        }
        int insert = crmOrderMapper.insert(updateOrder);
        if (insert > 0) {
            jdLogisticsService.traceSubscribe(crmOrder);

            AsyncManager.me().execute(() -> {
                updateOrder.getProductCollection().parallelStream().forEach(item -> {
                    CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
                    crmProductStockRecord.setProductId(item.getProductId());
                    crmProductStockRecord.setOrderId(crmOrder.getOrderId());
                    crmProductStockRecord.setOrderStatus(1);
                    crmProductStockRecord.setChangeQuantity(Convert.toLong(item.getNum()));
                    crmProductService.stockOperation(crmProductStockRecord, OperationTypeEnum.REDUCE);
                });
                return Boolean.TRUE;
            });
        }
        return commShipping(updateOrder, insert);
    }

    /**
     * 追加补货单
     * @param request
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int appendRepurchase(AppendRepurchaseOrderRequest request) {
        CrmOrder crmOrder = this.getById(request.getRelatedOrderId());
        if (crmOrder == null) {
            throw new ServiceException("订单不存在");
        }
        CrmOrder updateOrder = BeanUtil.copyProperties(request, CrmOrder.class);
        updateOrder.setRelatedOrderId(request.getRelatedOrderId());
        updateOrder.setShippingType(request.getShippingType());
        updateOrder.setOrderType(2);
        updateOrder.setOrderStatus(140);
        updateOrder.setIsReplenishOrder(0);
        updateOrder.setSalesmanId(crmOrder.getSalesmanId());
        updateOrder.setSalesmanName(crmOrder.getSalesmanName());
        updateOrder.setCustomerId(crmOrder.getCustomerId());
        updateOrder.setReceiverName(crmOrder.getReceiverName());
        updateOrder.setReceiverPhone(crmOrder.getReceiverPhone());
        updateOrder.setReceiverAddress(crmOrder.getReceiverAddress());
        updateOrder.setPaymentMethod(crmOrder.getPaymentMethod());
        updateOrder.setPaymentName(crmOrder.getPaymentName());
        updateOrder.setIsBigOrder(request.getIsBigOrder());
        updateOrder.setIsFixed(request.getIsFixed());
        updateOrder.setProductCollection(request.getProductCollection());
        updateOrder.setOrderCount(crmOrder.getOrderCount());
        updateOrder.setIsDelayedDelivery(request.getIsDelayedDelivery());
        updateOrder.setOrderRemark(request.getOrderRemark());
        updateOrder.setCodAmount(request.getCodAmount());
        updateOrder.setActualPrice(request.getActualPrice());
        updateOrder.setTotalAmount(request.getTotalAmount());
        updateOrder.setTotalAmount(request.getTransferOrderAmount());
        updateOrder.setOrderRemark(request.getOrderRemark());
        Long count = crmOrderMapper.selectCount(Wrappers.<CrmOrder>lambdaQuery().eq(CrmOrder::getCustomerId, crmOrder.getCustomerId()).eq(CrmOrder::getOrderType, crmOrder.getOrderType()));
        crmOrder.setOrderCount(count + 1);

        String sn = RedisSnGenerator.build().getBusSn(RedisSnEnum.REPURCHASE_ORDER);
        updateOrder.setOrderNo(sn);
        if (StringUtils.isNotBlank(request.getLogisticsPlatformCode())){
            updateOrder.setLogisticsPlatformCode(request.getLogisticsPlatformCode());
            updateOrder.setLogisticsPlatform(ExpressCompanyEnum.getByCode(request.getLogisticsPlatformCode()).getName());
        }
        if (StringUtils.isNotBlank(request.getLogisticsNo())) {
            updateOrder.setLogisticsStatus("3");
            updateOrder.setLogisticsProgress("已发货");
            updateOrder.setOrderStatus(150);
        }

        updateOrder.getProductCollection().parallelStream().forEach(item -> {
            CrmProductStockRecord crmProductStockRecord = new CrmProductStockRecord();
            crmProductStockRecord.setProductId(item.getProductId());
            crmProductStockRecord.setOrderId(crmOrder.getOrderId());
            crmProductStockRecord.setOrderStatus(1);
            crmProductStockRecord.setChangeQuantity(Convert.toLong(item.getNum()));
            crmProductService.stockOperation(crmProductStockRecord, OperationTypeEnum.REDUCE);
        });

        int insert = crmOrderMapper.insert(updateOrder);
        if (insert > 0) {
            jdLogisticsService.traceSubscribe(crmOrder);
        }
        return commShipping(updateOrder, insert);
    }


    private CrmCustomer saveCustomer(BaiDuJianKangApi.OrderDetailResponse order,CrmOrder crmOrder) {
        CrmCustomer crmCustomer = new CrmCustomer();
        crmCustomer.setCustomerSource("baidu");
        crmCustomer.setCustomerName(crmOrder.getReceiverName());
        crmCustomer.setCustomerPhone(crmOrder.getReceiverPhone());
        crmCustomer.setContactAddress(crmOrder.getReceiverAddress());
        crmCustomer.setOrderTime(crmOrder.getOrderTime());

        LambdaQueryWrapper<CrmCustomer> wrapper = Wrappers.<CrmCustomer>lambdaQuery().eq(CrmCustomer::getCustomerPhone, crmCustomer.getCustomerPhone()).last("limit 1");
        boolean flg;
        CrmCustomer crmCustomer1 = crmCustomerMapper.selectOne(wrapper);
        if (crmCustomer1 != null) {
            crmCustomer.setCustomerId(crmCustomer1.getCustomerId());
            flg = crmCustomerMapper.update(crmCustomer, wrapper) > 0;
        }else {
            crmCustomer.setCustomerId(IdWorker.getId());
            flg = crmCustomerMapper.insert(crmCustomer) > 0;
        }

        if (!flg) {
            log.error("客户同步失败：{}", crmCustomer.getCustomerPhone());
        }

        return crmCustomer;
    }


    /**
     * 合并订单数据
     * @param list
     * @param request
     */
    @Override
    public void combineOrderData(List<CrmOrder> list, CrmOrder request) {
        Authentication authentication = SecurityUtils.getAuthentication();
        Set<Long> customerIds = list.stream().map(CrmOrder::getCustomerId).filter(Objects::nonNull).collect(Collectors.toSet());
        Map<String, HashMap<@Nullable String, @Nullable Object>> customerMap = customerIds.parallelStream().map(customerId -> {
            SecurityUtils.setAuthentication(authentication);
            HashMap<@Nullable String, @Nullable Object> map = Maps.newHashMap();
            CrmUserFollowRecord followRecord1 = new CrmUserFollowRecord();
            followRecord1.setCustomerId(customerId);
            followRecord1.setTypeCode("1");
            followRecord1.setUserId(request.getSalesmanId());
            map.put("customerId", customerId);
            CrmUserFollowRecord latestRecord1 = crmUserFollowRecordService.getLatestRecord(followRecord1);
            map.put("latestRecord1", latestRecord1);
            followRecord1.setTypeCode("2");
            CrmUserFollowRecord latestRecord2 = crmUserFollowRecordService.getLatestRecord(followRecord1);
            map.put("latestRecord2", latestRecord2);
            CrmOrder historicalAmount = this.getOne(Wrappers.<CrmOrder>query().select("customer_id", "sum(COALESCE(total_amount,0)) as total_amount").eq("customer_id", customerId).eq(ObjUtil.isNotEmpty(request.getOrderType()), "order_type", request.getOrderType()).eq("is_children", 0).groupBy("customer_id"));
            map.put("historicalAmount", (Opt.ofNullable(historicalAmount).map(CrmOrder::getTotalAmount).orElse(BigDecimal.ZERO)));
            CrmOrder recentAmount = this.getOne(Wrappers.<CrmOrder>query().select("customer_id", "total_amount").eq("customer_id", customerId).eq(ObjUtil.isNotEmpty(request.getOrderType()), "order_type", request.getOrderType()).eq("is_children", 0).orderByDesc("order_time", "create_time").last("limit 1"));
            map.put("recentAmount", (Opt.ofNullable(recentAmount).map(CrmOrder::getTotalAmount).orElse(BigDecimal.ZERO)));
            Optional<CrmUserFollowRecord> followRecord = crmUserFollowRecordService.getOneOpt(Wrappers.<CrmUserFollowRecord>query().eq("customer_id", customerId).orderByDesc("usage_end_time").last("limit 1"));
            map.put("usageEndTime", followRecord.map(CrmUserFollowRecord::getUsageEndTime).orElse(null));
            return map;
        }).collect(Collectors.toMap(map -> map.get("customerId").toString(), map -> map));
        list.parallelStream().forEach(order -> {
            SecurityUtils.setAuthentication(authentication);
            if (order.getIsMultiPackage() != null && order.getIsMultiPackage() == 1) {
                QueryWrapper<CrmOrder> wrapper = Wrappers.<CrmOrder>query()
                        .eq("crm_order.related_order_id", order.getOrderId())
                        .eq("crm_order.is_children", 1)
                        .eq("crm_order.order_type", request.getOrderType());
                List<CrmOrder> childOrders = this.selectCrmOrderList(new CrmOrder(), wrapper);
                order.setChildrens(childOrders);
            }
            if (order.getCustomerId() != null) {
                HashMap<@Nullable String, @Nullable Object> hashMap = customerMap.get(order.getCustomerId().toString());
                if (hashMap != null) {
                    CrmUserFollowRecord latestRecord1 = (CrmUserFollowRecord) hashMap.get("latestRecord1");
                    CrmUserFollowRecord latestRecord2 = (CrmUserFollowRecord) hashMap.get("latestRecord2");
                    order.setFollowRemark1((Opt.ofNullable(latestRecord1).map(CrmUserFollowRecord::getFollowRemark).orElse(null)));
                    order.setFollowRemark2((Opt.ofNullable(latestRecord2).map(CrmUserFollowRecord::getFollowRemark).orElse(null)));
                    BigDecimal historicalAmount = (BigDecimal) hashMap.get("historicalAmount");
                    BigDecimal recentAmount = (BigDecimal) hashMap.get("recentAmount");
                    order.setHistoricalAmount(historicalAmount);
                    order.setRecentAmount(recentAmount);
                    Date usageEndTime = (Date) hashMap.get("usageEndTime");
                    order.setUsageEndTime(usageEndTime);
                }
            }
        });
    }

    @Override
    public List<CrmOrder> selectHighSeasOrderList(CrmOrder crmOrder) {
        return  baseMapper.selectHighSeasOrderList(crmOrder);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int verification(VerificationOrderRequest request) {
        CrmOrder crmOrder = getById(request.getOrderId());
        if (crmOrder == null) {
            throw new ServiceException("订单不存在");
        }
        if (!crmOrder.getOrderStatus().equals(CrmOrderStatus.COMPLETED.getCode())) {
            throw new ServiceException("订单未完成");
        }
        if (crmOrder.getIsWriteOff() == 1) {
            throw new ServiceException("订单已核销");
        }
        if (crmOrder.getIsMultiPackage() == 1) {
            LambdaUpdateWrapper<CrmOrder> wrapper = Wrappers.<CrmOrder>lambdaUpdate()
                    .set(CrmOrder::getIsWriteOff, 1)
                    .set(CrmOrder::getVerTime, DateUtil.date())
                    .set(CrmOrder::getVerRemark, request.getVerRemark())
                    .eq(CrmOrder::getRelatedOrderId, crmOrder.getOrderId())
                    .eq(CrmOrder::getIsChildren, 1)
                    .eq(CrmOrder::getOrderType, OrderType.REPURCHASE.getType());
            this.update(wrapper);
        }
        return baseMapper.updateById(CrmOrder.builder().orderId(request.getOrderId()).isWriteOff(1).verRemark(request.getVerRemark()).build());
    }

    /**
     * 订单完成
     * @param request
     * @return
     */
    @Override
    public int completeOrder(CompleteOrderRequest request) {
        CrmOrder crmOrder = getById(request.getOrderId());
        if (crmOrder == null) {
            throw new ServiceException("订单不存在");
        }
        if (!Arrays.asList(CrmOrderStatus.COMPLETED.getCode(),CrmOrderStatus.SIGNED.getCode()).contains(crmOrder.getOrderStatus())) {
            throw new ServiceException("订单非带完成状态");
        }
        if (crmOrder.getIsMultiPackage() == 1) {
            LambdaUpdateWrapper<CrmOrder> wrapper = Wrappers.<CrmOrder>lambdaUpdate()
                    .set(CrmOrder::getOrderStatus, CrmOrderStatus.COMPLETED.getCode())
                    .eq(CrmOrder::getRelatedOrderId, crmOrder.getOrderId())
                    .eq(CrmOrder::getIsChildren, 1)
                    .eq(CrmOrder::getOrderType, OrderType.REPURCHASE.getType());
            this.update(wrapper);
        }
        return baseMapper.updateById(CrmOrder.builder().orderId(request.getOrderId()).orderStatus(CrmOrderStatus.COMPLETED.getCode()).build());
    }

    /**
     * 公共物流发货
     * @param crmOrder
     * @param insert
     * @return
     */
    private int commShipping(CrmOrder crmOrder, int insert) {
        if (insert > 0 && crmOrder.getShippingType() == ShippingType.SYSTEM_SHIPPING.getType() && crmOrder.getIsDelayedDelivery() == 0) {
            LogisticsShippingRequest shippingRequest = new LogisticsShippingRequest();
            shippingRequest.setOrderId(crmOrder.getOrderId());
            shippingRequest.setShippingType(crmOrder.getShippingType());
            shippingRequest.setLogisticsPlatformCode(crmOrder.getLogisticsPlatformCode());
            shippingRequest.setRemark(crmOrder.getRemark());
            this.logisticsShipping(shippingRequest);
        }
        return insert;
    }
}
